/*
 * Fecha:  29-11-2010
 * @author Paco FELC
 *
    Cuando un jugador gana un partido a un rival con mayor nivel que el avanza la mitad de las posiciones
 *  que les separan.
 *  Si el Primero pierde con el segundo el segundo pasa a ser el primero.
 *
 *  Si el primero pierde con el 10 el decimo sube hasta la quinta posicion.
 */

package com.bitoon.basketdudes.ws;
import org.apache.log4j.*;
import com.bitoon.basketdudes.jpa.*;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author paco
 *
 * Funciones que bloquean
 *
 * bajada (desde el inicio al fin del proceso)
 * TareaPartidos ( desde el inicio al fin del proceso)
 *
 * Esta dos tareas son excluyentes
 *
 */
public class Rank {
    Logger           log         = Logger.getLogger(DatosEquipo.class);
    EntityManagerFactory    emf     = null;
    EntityManager           em_rank = null;


    public Rank( ) {
        try {
            // JPA Units
            emf = PersistenceManager.getInstance().getEntityManagerFactory("jpa_basket");
        } catch (Exception e) {
            log.error("[ERROR][constructor]: No se puedo conectar a la base de datos: " , e);
        }
    }

    /*
    public void setEntityManager ( EntityManager p_basket ) {
        try {
            // JPA Units
            em_rank   = p_basket;
        } catch (Exception e) {
            log.error("[ERROR][constructor]: No se puedo conectar a la base de datos: " , e);
        }
    }
     *
     */

    public EntityManager getEntityManager (  ) {
        try {
            if ( em_rank == null) {
                emf      = PersistenceManager.getInstance().getEntityManagerFactory("jpa_basket");
                em_rank  = emf.createEntityManager();
            }

        } catch (Exception e) {
            log.error("[ERROR][constructor]: No se puedo conectar a la base de datos: " , e);
        }
        return em_rank;
    }

    public int getRankingEquipo ( int equipo_id, EntityManager p_em ) {
        // Consulta la posición en el ranking de un equipo
        // -1: si no tiene posición en el ranking

        try {
            Query query = p_em.createNamedQuery("Ranking.findById");
            query.setParameter ("id", equipo_id);
            Ranking r_ranking = (Ranking)query.getSingleResult();
            
            if ( r_ranking != null)
                return  r_ranking.getPosicion();
            else
                return 0;
        } catch (NoResultException nre) {
            return -1;
        } catch (Exception e) {
           log.error("[ERROR][Leer Partido]: " , e);
           return -1;
        } 
    }
/*
    public int getRankingEquipo ( int equipo_id ) {
        // Consulta la posición en el ranking de un equipo
        //  -1: si no tiene posición en el ranking

        try {
            em_rank = emf.createEntityManager(); // check 08.08.2012

            Query query = em_rank.createNamedQuery("Ranking.findById");
            query.setParameter ("id", equipo_id);
            Ranking r_ranking = (Ranking)query.getSingleResult();
            return r_ranking.getPosicion();

        } catch (NoResultException nre) {
            return -1;
        } catch (Exception e) {
           log.error("[ERROR][Leer Partido]: " , e);
           return -1;
        } finally {
            try { em_rank.close(); } catch (Exception e) { } // revisado 09/08/2012
        }
    }
*/
    public int wsTareaPartidos ( HttpServletRequest p_request, HttpServletResponse response ) {
        /* Seleccionamos los partidos que no tengan las posiciones calculadas
         * ordenados por fecha de celebración del más antiguo al más moderno
         */
        int     retorno=0;
        boolean quedan = true;
        int     procesados_total = 0;
        try {
            log.debug ("Procesando Partidos Pendientes " );
            em_rank = emf.createEntityManager(); // check 08.08.2012

            while ( quedan == true ) {
                em_rank.getTransaction().begin();
                if ( retorno==0 && hayBloqueoRanking() != 0 ) {
                    log.error("[BLOQUEO][TareaPartidos Intentar mas tarde] " + "TareaPartidos" );
                    retorno=-2;
                }

                if ( retorno == 0 && Bloquear( em_rank ) != 0) {
                    log.error("[BLOQUEO][NO HE PODIDO BLOQUEAR. Intentar mas tarde] " );
                    retorno=-3;
                }
    log.debug ("Bloqueo mio TareaPartidos " );
                if ( retorno==0 ) {
                    Query q=em_rank.createQuery("SELECT p FROM ColaPartido p order by p.fecha");
                    List<ColaPartido> lista = q.getResultList();

                    if ( lista.size() == 0 ) {
                        quedan = false;
    log.error ("::::Tarea Partidos: No hay partidos pendientes " );
                    } else {
    log.error (":::::::::::::::::::::::::::::::::: "+procesados_total   );
    log.error ("::::Tarea Partidos: Quedan         "+lista.size() );
                        int partido_id;
                        int cuantos_quedan=10;
                        if ( lista.size()< 10 )
                            cuantos_quedan=lista.size();
                        
                        for ( int i=0;i< cuantos_quedan; i++) {
                            procesados_total++;
                            partido_id = lista.get(i).getId();
                            try {
                                Query query = em_rank.createNamedQuery("Partido.findById");
                                query.setParameter ("id", partido_id);
                                Partido r_partido = (Partido)query.getSingleResult();

                                /* Actualizamos el ranking del partido */
                                UpdateRank( r_partido );
                            } catch (NoResultException nre) {
                                log.error("[ERROR][PARTIDO COLA NO EXISTE]: " +  lista.get(i).getId() );
                            } catch (Exception e) {
                               log.error("[ERROR][Leer Partido]: " , e);
                            }
                            em_rank.remove( lista.get(i) );
                            em_rank.flush();
                        }
                    }
                    Desbloquear( em_rank );
                    em_rank.getTransaction().commit();
                }
            }
            retorno=0;
       } catch (Exception e) {
           log.error("[ERROR][TareaPartidos]: " , e);
           em_rank.getTransaction().rollback();
           retorno = -4;
       } finally {
           try { em_rank.close(); } catch (Exception e) { } // revisado 09/08/2012
       }
       return retorno;
    }


    public void UpdateRank ( Partido p_partido) {
        int e_ganador_id;
        int e_perdedor_id;
        Ranking r_ganador           = null;
        Ranking r_perdedor          = null;
        Ranking r_ultimo            = null;
        int     posiciones_ganadas  = 0;
/*
        if ( hayBloqueoRanking() != 0 ) {
            log.debug("[BLOQUEO][Intentar mas tarde] "+"UpdateRank" );
            return;
        }3
*/

        if ( p_partido.getPuntos1()>p_partido.getPuntos2() ) {
            e_ganador_id  = p_partido.getEquipoId1();
            e_perdedor_id = p_partido.getEquipoId2();
        } else {
            e_ganador_id  = p_partido.getEquipoId2();
            e_perdedor_id = p_partido.getEquipoId1();
         }

log.debug("Calculando Ranking Partido: " + p_partido.getId() );
        /* Cargamos el ranking del ganador */
        try {
log.debug(" Voy a buscar ganador " + e_ganador_id );
            r_ganador = (Ranking)em_rank.find(Ranking.class, e_ganador_id);
//        } catch (NoResultException nre) {
            if ( r_ganador == null ) {
log.debug(" Ganador nuevo en ranking" + e_ganador_id );
                r_ganador = new Ranking ();
                r_ganador.setId(e_ganador_id);

                Query query=em_rank.createQuery("SELECT p FROM Ranking p WHERE p.posicion = (SELECT MAX(p.posicion) FROM p)");
                r_ultimo = (Ranking)query.getSingleResult();

log.debug("Ultima posicion " + r_ultimo.getPosicion()  );

                r_ganador.setPosicion   ( r_ultimo.getPosicion() + 1 ); // Le ponemos en la última posición del ranking
                r_ganador.setAntPosicion( r_ultimo.getPosicion() + 1 ); // Su anterior posición es la misma

                em_rank.persist( r_ganador );
            }
        } catch (Exception e) {
            log.error("[ERROR][Leer ganador]: " , e);
            r_ganador = new Ranking ();
            r_ganador.setId(e_ganador_id);

            r_ganador.setPosicion(1);
            r_ganador.setAntPosicion(1);
            r_ganador.setId(e_ganador_id);
            em_rank.persist( r_ganador );
        }

// 07/03/2011 No actualizamos el ranking en el equipo
//        e_ganador.setRanking((short)r_ganador.getPosicion());
// --------------------------------------------------

        /* Cargamos el ranking del perdedor */
        try {
log.debug(" Voy a buscar perdedor " + e_perdedor_id );
            r_perdedor = (Ranking)em_rank.find(Ranking.class, e_perdedor_id);
//        } catch (NoResultException nre) {
            if ( r_perdedor == null ) {
log.debug(" Perdedor nuevo en ranking" + e_perdedor_id );
                r_perdedor = new Ranking ();
                r_perdedor.setId(e_perdedor_id);

                Query query=em_rank.createQuery("SELECT p FROM Ranking p WHERE p.posicion = (SELECT MAX(p.posicion) FROM p)");
                r_ultimo = (Ranking)query.getSingleResult();

log.debug("Ultima posicion " + r_ultimo.getPosicion()  );

                r_perdedor.setPosicion   ( r_ultimo.getPosicion() + 1 ); // Le ponemos en la última posición del ranking
                r_perdedor.setAntPosicion( r_ultimo.getPosicion() + 1 ); // Su anterior posición es la misma

                em_rank.persist( r_perdedor );
            }
        } catch (Exception e) {
            log.error("[ERROR][Leer perdedor]: " , e);
        }

        /* Actualizamos las posiciones iniciales en el partido */
        if ( p_partido.getEquipoId1() == r_ganador.getId() ) {
            p_partido.setPos1Ini(r_ganador.getPosicion());
            p_partido.setPos2Ini(r_perdedor.getPosicion());
        } else {
            p_partido.setPos1Ini(r_perdedor.getPosicion());
            p_partido.setPos2Ini(r_ganador.getPosicion());
        }

        /* Buscamos si hay defensa activa o no */
        ActualizarDefensa ( r_ganador, r_perdedor);

        /* Si el ganador tiene un ranking mayor que el perdedor no se mueven las posiciones */
        if ( r_ganador.getPosicion() > r_perdedor.getPosicion())
        {
            //posiciones_ganadas = (r_ganador.getPosicion() - r_perdedor.getPosicion() +1 ) / 2;
            posiciones_ganadas = (r_ganador.getPosicion() - r_perdedor.getPosicion()  ) / 2;

            log.debug("Posiciones Ganadas " + posiciones_ganadas  );
            log.debug("Inicial Ganador "    + r_ganador.getPosicion()  );
            log.debug("Inicial Perdedor "   + r_perdedor.getPosicion()  );

            try {
                Query query = em_rank.createNamedQuery("Ranking.findByRangoPosicion");
                query.setParameter ("min_pos", r_ganador.getPosicion() - posiciones_ganadas);
                query.setParameter ("max_pos", r_ganador.getPosicion());                     ;

                List<Ranking> results = query.getResultList();
log.debug( "Tamaño lista " + results.size() + " min_pos:" + 
        (r_ganador.getPosicion() - posiciones_ganadas) + " max_pos: " + r_ganador.getPosicion());
                for (Ranking p : results) {
                      if (p.getPosicion() == r_ganador.getPosicion() && p.getId()== r_ganador.getId()) {
log.debug("Sube " + posiciones_ganadas + " puesto " + p.getPosicion() + " " + p.getId()  );
                          p.setAntPosicion(p.getPosicion());
                          p.setPosicion(p.getPosicion()-posiciones_ganadas);
                      } else {
log.debug("Baja 1 puesto " + p.getPosicion() + " " + p.getId()  );
                          p.setAntPosicion(p.getPosicion());
                          p.setPosicion(p.getPosicion()+1);
                      }
                }

                /* Si el que estaba por delante en el ranking ha perdido y no le ha sobrepasado
                 * el ganador del partido, intercambiamos su posición con el siguiente del ranking
                 * para que baje un puesto
                 */
log.debug("[Ranking][xxx] "+ r_ganador.getPosicion() + " - " + r_perdedor.getPosicion() );
                if ( r_ganador.getPosicion() > r_perdedor.getPosicion() ) {
                    Ranking r_posterior = null;
                    Query q_posterior = em_rank.createNamedQuery("Ranking.findByPosicion");
                    q_posterior.setParameter ("posicion", r_perdedor.getPosicion()+1);
                    try {
                        r_posterior = (Ranking)q_posterior.getSingleResult();
                        r_posterior.setAntPosicion(r_posterior.getPosicion());
                        r_posterior.setPosicion   (r_posterior.getPosicion()-1);

                        r_perdedor.setAntPosicion( r_perdedor.getPosicion() );
                        r_perdedor.setPosicion   ( r_perdedor.getPosicion()+1 );

log.debug("[posterior] "+ r_posterior.getId() + " nueva posicion: " + r_posterior.getPosicion());
log.debug("[perdedor]  "+ r_perdedor.getId() + " nueva posicion: " + r_perdedor.getPosicion());
                    } catch (NoResultException nre) {
                        log.debug("NO HAY POSTERIOR A LA POSICION " + r_ganador.getPosicion() );
                    }
                }
            } catch (Exception e) {
                log.error("[rank]: " , e);

            }
        } else {
            log.debug("RANKING SE QUEDA COMO ESTA" + r_ganador.getPosicion() + " " + r_perdedor.getPosicion() + " "
                    + (r_ganador.getPosicion() < r_perdedor.getPosicion()) );

            /* Actualizamos las posiciones ganadas o perdidas para que salga el símbolo = */
            r_ganador.setAntPosicion(r_ganador.getPosicion());
            r_perdedor.setAntPosicion(r_perdedor.getPosicion());

        }
// 07/03/2011 No actualizamos el ranking en el equipo
//        e_perdedor.setRanking((short)r_perdedor.getPosicion());
// ----------------------------------------------------------

        /* Actualizamos las posiciones finales en el partido */
        if ( p_partido.getEquipoId1() == r_ganador.getId() ) {
            p_partido.setPos1Fin(r_ganador.getPosicion());
            p_partido.setPos2Fin(r_perdedor.getPosicion());
        } else {
            p_partido.setPos1Fin(r_perdedor.getPosicion());
            p_partido.setPos2Fin(r_ganador.getPosicion());
        }


        /* PENDIENTE Actualizamos los partidos jugados del ganador */

        /* PENDIENTE Actualizamos los partidos jugados del perdedor */

    }

    /* Devuelve -1 si hay error
     *           1 si hay que reordenar el array.
     *           0 si NO hay que reordenar array
     */
    public int defensa (EntityManager emt) {
        int           retorno;
        int           alguno=0;
        List<Defensa> lista=null;

        try {

/*
            if ( hayBloqueoRanking() != 0 ) {
                log.debug("[BLOQUEO][Defensa Intentar mas tarde] "+"defensa" );
                return -2;
            }
*/
            Date fecha   = Util.FechaSiguiente(0);

            // Buscamos los equipos que tenían que defender posicion a fecha de hoy o anterior
            Query q=emt.createQuery ("SELECT d FROM Defensa d where d.fDefensa <:fecha ");
            q.setParameter("fecha"  , fecha);
            lista = q.getResultList();
            if ( lista!= null && !lista.isEmpty() ) {
                for ( int i=0;i<lista.size();i++) {
                    Defensa defensa = lista.get(i);

                    // Si no está entre los primeros no hay nada que defender
                    Query query = emt.createNamedQuery("Ranking.findById");
                    query.setParameter ("id",lista.get(i).getId() );
log.info ("Buscando Ranking " + lista.get(i).getId() );

                    Ranking r_ultimo = null;
                    try {
                        r_ultimo = (Ranking)query.getSingleResult();
                    } catch ( NoResultException nre ) { }

                    if ( r_ultimo == null || r_ultimo.getPosicion()>100 ) {
                        // Ya no está en el ranking borramos su defensa
log.info ("Ha perdido posición " + defensa.getId() + " -> " +defensa.getContraLider() +":"+ defensa.getContraResto() );
                        emt.remove(defensa);
                    } else {

                        if ( defensa.getContraLider() >4 && defensa.getContraResto() >4) {
log.info ("Mantiene defensa " + r_ultimo.getId() + " -> " +defensa.getContraLider() +":"+ defensa.getContraResto() );
                            // ha defendido resetamos su defensa
                            ResetDefensa(emt,defensa);
                        } else {
                            // no ha defendido le penalizamos y borramos su defensa
                            emt.remove(defensa);

                            r_ultimo.setAntPosicion(r_ultimo.getPosicion());
                            r_ultimo.setPosicion(r_ultimo.getPosicion()+50);
 log.info ("+50 " + r_ultimo.getId() + " -> " +defensa.getContraLider() +":"+ defensa.getContraResto() );
                            emt.persist(r_ultimo);
                            alguno++;
                        }
                    }
                }
                // Vamos guardando cambios, aunque si hay rollback se desharán
                emt.flush();
            }
            retorno = 0;
        } catch (Exception e) {
                log.error("[ERROR][defensa]: " , e);
            retorno = -1;
        } finally {
            
        }
        return alguno;
    }
/*
    public static void main(String[] args) {

        Rank obj_ranking = new Rank();

//        obj_ranking.defensa ( );

//        System.out.println(" "+f_anterior);
    }
*/
    public String wsBajada (HttpServletRequest p_request, HttpServletResponse response) {
log.debug("-------COMIENZA-------------");
log.debug("--------BAJADA--------------");
        Date f_fin;
        Date f_ini;
        EntityManager emt = null;
        String retorno="";
        boolean alguno = false;

        try {
            emt = emf.createEntityManager(); // check 07.08.2012
            emt.getTransaction().begin();

            // Hasta que no bloqueemos el ranking insistimos
            int ret = Bloquear( emt );
            if  ( ret != 0 ) {
                retorno="error=-2";
                return retorno;
            }
log.debug ("Bloqueo mio bajada " );
            // Comprobamos a los que defienden las primeras posiciones
            int ret_defensa = defensa( emt );
            if ( ret_defensa != -1) {
                if ( ret_defensa>0 )
                    alguno = true;

                // Buscamos equipos que no hayan jugado las últimas cuatro semanas
                f_ini   = Util.FechaSiguiente(-35);
                f_fin   = Util.FechaSiguiente(-28);
log.info("-----------------------------");
log.info("[4 semanas]"+f_ini+ "-"+f_fin);
                List<Ranking> lista = ConsultarRankingFechas ( emt, f_ini, f_fin) ;
                if ( lista!= null && !lista.isEmpty() ) {
                    for ( int i=0;i<lista.size();i++) {
                         emt.remove(lista.get(i));
                        // Vamos guardando cambios, aunque si hay rollback se desharán
                        emt.flush();
log.info (" x " + lista.get(i).getId() + " " + lista.get(i).getPosicion() );
                    }
                    alguno = true;
                }

                // Buscamos equipos que no hayan jugado las últimas tres semanas
                f_ini   = Util.FechaSiguiente(-22);
                f_fin   = Util.FechaSiguiente(-21);
log.info("-----------------------------");
log.info("[3 semanas]"+f_ini+ "-"+f_fin);
                lista = ConsultarRankingFechas ( emt, f_ini, f_fin) ;
                if ( lista!= null && !lista.isEmpty() ) {
                    for ( int i=0;i<lista.size();i++) {
                        lista.get(i).setAntPosicion(lista.get(i).getPosicion());
                        lista.get(i).setPosicion(lista.get(i).getPosicion()+40);
log.info ("+40 " + lista.get(i).getId() + " " + lista.get(i).getPosicion() );
                        // Vamos guardando cambios, aunque si hay rollback se desharán
                        emt.flush();
                    }
                    alguno = true;
                }

                // Buscamos equipos que no hayan jugado las últimas dos semanas
                f_ini   = Util.FechaSiguiente(-15);
                f_fin   = Util.FechaSiguiente(-14);
log.info("-----------------------------");
log.info("[2 semanas]"+f_ini+ "-"+f_fin);
                lista = ConsultarRankingFechas ( emt, f_ini, f_fin) ;
                if ( lista!= null && !lista.isEmpty() ) {
                    for ( int i=0;i<lista.size();i++) {
                        lista.get(i).setAntPosicion(lista.get(i).getPosicion());
                        lista.get(i).setPosicion(lista.get(i).getPosicion()+20);
log.info ("+20 " + lista.get(i).getId() + " " + lista.get(i).getPosicion() );
                        // Vamos guardando cambios, aunque si hay rollback se desharán
                        emt.flush();
                    }
                    alguno = true;
                }

                // Buscamos equipos que no hayan jugado las última semanas
                f_ini = Util.FechaSiguiente(-8);
                f_fin = Util.FechaSiguiente(-7);
log.info("-----------------------------");
log.info("[1 semanas]"+f_ini+ "-"+f_fin);
                lista = ConsultarRankingFechas ( emt, f_ini, f_fin) ;
                if ( lista!= null && !lista.isEmpty() ) {
                    for ( int i=0;i<lista.size();i++) {
                        lista.get(i).setAntPosicion(lista.get(i).getPosicion());
                        lista.get(i).setPosicion(lista.get(i).getPosicion()+10);
log.info ("+10 " + lista.get(i).getId() + " " + lista.get(i).getPosicion() );
                        // Vamos guardando cambios, aunque si hay rollback se desharán
                        emt.flush();
                    }
                    alguno = true;
                }

                if ( alguno ) {
                    // Reordenar
                    Reordenar( emt );
                }
                Desbloquear( emt );

//Thread.sleep(20000);

                emt.getTransaction().commit();
                retorno = "error=0";
            } else {
                emt.getTransaction().rollback();
                retorno = "error=-1";
            }
        } catch (Exception e) {
            log.error("[ERROR][constructor]: EMT base de datos: " , e);
            emt.getTransaction().rollback();
            retorno = "error=-1";
        } finally {

            try { if (emt != null) emt.close(); } // revisado 09/08/2012
            catch (Exception e) {
                log.error("[ERROR][constructor]: EMT base de datos: " , e);
            }
        }
        return retorno;
    }

    private void Reordenar ( EntityManager emt ) {
        List<Ranking> lista;

        // Reordenamos el ranking
        Query q=emt.createQuery ("SELECT r FROM Ranking r order by r.posicion,r.id");
        lista = q.getResultList();
        int contador =1;

        if ( !lista.isEmpty() ) {
            for ( int i=0;i<lista.size();i++) {
                if ( contador<=100 ) {
                    CrearDefensa( emt, lista.get(i).getId() );
                }
log.debug ("" + lista.get(i).getId() + " " + lista.get(i).getPosicion() );
                if ( lista.get(i).getPosicion() != contador) {
log.debug ("muevo a " + contador );
                    lista.get(i).setPosicion(contador);
                }
                contador++;
            }
        }
    }

    /* Devuelve elementos del ranking entre fechas */
    List<Ranking> ConsultarRankingFechas ( EntityManager emt, Date f_ini, Date f_fin  ) {

//log.debug("[fechas ranking]"+f_ini+ "-"+f_fin);


        Query q=emt.createQuery
        ("SELECT r FROM Equipo e, Ranking r  where e = r.id and e.fUltimo between :f_ini AND :f_fin)");
        q.setParameter("f_ini"  , f_ini);
        q.setParameter("f_fin"  , f_fin);

        List<Ranking>lista = q.getResultList();
        if ( !lista.isEmpty() ) {
log.debug("lista de:" + lista.size());
            return lista;
        }  else {
log.debug("lista vacia:");
            return null;
        }
    }

    /* Devuelve partidos entre dos equipos entre fechas */
    List<Partido> ConsultarPartidosFechas ( EntityManager emt, Date f_ini, Date f_fin, int p_id1, int p_id2  ) {

//log.debug("[fechas partidos]"+f_ini+ "-"+f_fin+" id "+p_id1+" "+p_id2);
        Query q=emt.createQuery
        ("SELECT p FROM Partido p where p.fPartido between :f_ini and :f_fin and ( (equipo_id1=:id1 and equipo_id2=:id2) or  (equipo_id1=:id3 and equipo_id2=:id4)) ");
        q.setParameter("f_ini"  , f_ini);
        q.setParameter("f_fin"  , f_fin);
        q.setParameter("id1"    , p_id1);
        q.setParameter("id2"    , p_id2);
        q.setParameter("id3"    , p_id2);
        q.setParameter("id4"    , p_id1);

        List<Partido>lista = q.getResultList();
        if ( !lista.isEmpty() ) {
//log.debug("partidos jugados:" + lista.size());
            return lista;
        }  else {
//log.debug("partidos lista vacia:");
            return null;
        }
    }


    public void ResetDefensa(EntityManager emt, Defensa defensa){
        defensa.setContraLider(0);
        defensa.setContraResto(0);
        defensa.setfDefensa(Util.FechaSiguiente(7));
        defensa.setfDefensa(Util.MachacaConHora(defensa.getfDefensa()));
        emt.persist(defensa);
    }

    void CrearDefensa(EntityManager emt, int p_id){

        Query query = em_rank.createNamedQuery("Defensa.findById");
        query.setParameter ("id",p_id );

        try {
            Defensa defensa = (Defensa)query.getSingleResult();
            if ( defensa != null )
                return;

        } catch (NoResultException nre) {
            Defensa defensa = new Defensa();
log.info ("Creando defensa" + p_id );
            defensa.setId(p_id);
            defensa.setContraLider(0);
            defensa.setContraResto(0);
            defensa.setfDefensa(Util.FechaSiguiente(8));
            defensa.setfDefensa(Util.MachacaConHora(defensa.getfDefensa()));

            emt.persist(defensa);
        }
    }

    int ActualizarDefensa ( Ranking r_ganador, Ranking p_rival ) {
        /* Buscamos enfrentamiento ultimos 15 dias */
        Date    f_ini   = Util.FechaSiguiente(-7);
        Date    f_fin   = Util.FechaSiguiente(0);
        Defensa defensa1=null;
        Defensa defensa2=null;
log.info("---ActualizarDensa---");

        /* Buscamos defensa  */
        Query query = em_rank.createNamedQuery("Defensa.findById");
        query.setParameter ("id",r_ganador.getId() );
        try {
            defensa1 = (Defensa)query.getSingleResult();
        } catch (NoResultException nre) {
            if ( r_ganador.getPosicion() <= 100 ) {
                CrearDefensa(em_rank, r_ganador.getId() );
            }
        } catch (Exception e) {
            log.error("[ERROR][Defensa]: " , e);
            return -1;
        }

        /* Buscamos defensa  */
        query = em_rank.createNamedQuery("Defensa.findById");
        query.setParameter ("id",p_rival.getId() );
        try {
            defensa2 = (Defensa)query.getSingleResult();
        } catch (NoResultException nre) {
            if ( p_rival.getPosicion() <= 100 ) {
                CrearDefensa(em_rank, p_rival.getId() );
            }
        } catch (Exception e) {
            log.error("[ERROR][Defensa]: " , e);
            return -1;
        }

        try {
            List<Partido> lista = ConsultarPartidosFechas ( em_rank, f_ini, f_fin,r_ganador.getId(),p_rival.getId() ) ;
//ERROR            if ( lista!= null && !lista.isEmpty() ) {
// 23/03/2011
            if ( lista!= null && lista.size()>1 ) {
                for ( int i=0;i<lista.size();i++)
                    log.info("[ultimos partidos]"+lista.get(i).getEquipoId1()+"-"+lista.get(i).getEquipoId2()+":"+lista.get(i).getFPartido());
log.info("[han jugado ultima semana]"+f_ini+ "-"+f_fin+" "+r_ganador.getId()+" "+p_rival.getId());
                return -2;
            } else {
log.info("[NO ultimos 15 dias]"+f_ini+ "-"+f_fin+" "+r_ganador.getId()+" "+p_rival.getId());
                if ( defensa1 != null ) {
                    if ( p_rival.getPosicion() <= 100 )
                        defensa1.setContraLider( defensa1.getContraLider() +1 );
                    else
                        defensa1.setContraResto( defensa1.getContraResto() +1 );
                    em_rank.persist(defensa1);
                }
                if ( defensa2 != null ) {
                    if ( r_ganador.getPosicion() <= 100 )
                        defensa2.setContraLider( defensa2.getContraLider() +1 );
                    else
                        defensa2.setContraResto( defensa2.getContraResto() +1 );
                    em_rank.persist(defensa2);
                }
            }
        } catch (Exception e) {
            log.error("[ERROR][Defensa ConsultarPartidosFechas]: " , e);
            return -1;
        }

        return 0;
    }


    int hayBloqueoRanking() {
// Los bloqueos no funcionan
//        Query bloqueo = em_rank.createNamedQuery( "RankingFecha.findByFIni" );
//        bloqueo.setLockMode(LockModeType.PESSIMISTIC_WRITE);

        try {
            // Bloqueamos la posicion 1 del ranking
            // para evitar la concurrencia de los procesos de defensa y bajada

            Query bloqueo=em_rank.createQuery("SELECT r FROM RankingFecha r where id=1");

            RankingFecha rf = (RankingFecha) bloqueo.getSingleResult();

            if ( rf == null || rf.getFIni()==null ) {
                log.debug("[No hay bloqueo]"  );
                return 0;  // No hay bloqueo
            }  else {
                log.debug("[HAY BLOQUEO] " + rf.getFIni() + " fin " + rf.getFFin() );
                return -1; // Hay bloqueo
            }
        } catch (Exception e) {
            log.error("[ERROR][Bloquear]: " , e);
            return -1;
        }

    }

    /* Ponemos fecha de inicio a la tabla rankingfecha para indicar que estamos
     * actualizando el ranking y no deben procesarse partidos o recalcular el ranking
     */
    int Bloquear( EntityManager p_em ) {
        try {
            Query bloqueo=em_rank.createQuery("SELECT r FROM RankingFecha r where id=1 ");

            RankingFecha rf = (RankingFecha) bloqueo.getSingleResult();

            if ( rf.getFIni() != null ) {
                return -1; // Hay bloqueo
            } else {
                rf.setFIni(Calendar.getInstance().getTime());
                em_rank.persist(rf);
                em_rank.flush();
                return 0;
            }
        } catch (NoResultException nre) {
            RankingFecha rf =  new RankingFecha();

            rf.setId(1);
            rf.setFIni(Calendar.getInstance().getTime());
            rf.setFFin(null);
            em_rank.persist(rf);

            return 0;

        } catch (Exception e) {
            log.error("[ERROR][Bloquear]: " , e);
            return -1;
        }

    }
    int Desbloquear( EntityManager p_em ) {
        try {
            Query bloqueo=em_rank.createQuery("SELECT r FROM RankingFecha r where id=1");

            RankingFecha rf = (RankingFecha) bloqueo.getSingleResult();

            if ( rf.getFIni() != null ) {
                rf.setFFin(rf.getFIni());
                rf.setFIni(null);

                em_rank.persist(rf);
                return 0;
            } else {
                return -2;
            }
        } catch (Exception e) {
            log.error("[ERROR][Bloquear]: " , e);
            return -1;
        }

    }








}
